package com.xdcplus.web.service.wip.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.xdcplus.core.utils.BeanUtils;
import com.xdcplus.exceptions.XdcWebException;
import com.xdcplus.mes.feign.workflow.ProcessRemote;
import com.xdcplus.mes.feign.workflow.RequestFlowRemote;
import com.xdcplus.mes.feign.workflow.RequestRemote;
import com.xdcplus.mes.feign.workflow.RequestTypeRemote;
import com.xdcplus.mes.feign.workflow.vo.RequestVO;
import com.xdcplus.mom.constants.AuthConstant;
import com.xdcplus.mom.constants.NumberConstant;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.mom.utils.AuthUtils;
import com.xdcplus.mom.utils.ResponseUtils;
import com.xdcplus.mp.service.impl.BaseServiceImpl;
import com.xdcplus.mp.utils.PageableUtils;
import com.xdcplus.mp.utils.PropertyUtils;
import com.xdcplus.pager.vo.PageVO;
import com.xdcplus.system.api.UserInfoRemote;
import com.xdcplus.web.common.pojo.dto.wip.WipTaskDTO;
import com.xdcplus.web.common.pojo.dto.wip.WipTaskFilterDTO;
import com.xdcplus.web.common.pojo.entity.wip.WipTask;
import com.xdcplus.web.common.pojo.entity.wip.WipTaskTarget;
import com.xdcplus.web.common.pojo.query.wip.WipTaskQuery;
import com.xdcplus.web.common.pojo.vo.wip.WipTaskVO;
import com.xdcplus.web.mapper.wip.WipTaskMapper;
import com.xdcplus.web.mapper.wip.WipTaskTargetMapper;
import com.xdcplus.web.service.wip.WipTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 岗位任务(WipTask)表服务实现类
 *
 * @author Devin.sang
 * @since 2023-07-03 13:30:08
 */
@Slf4j
@Service("wipTaskService")
public class WipTaskServiceImpl extends BaseServiceImpl<WipTaskMapper, WipTask, WipTask, WipTaskVO> implements WipTaskService {

    @Autowired
    protected WipTaskMapper wipTaskMapper;

    @Autowired
    protected WipTaskTargetMapper wipTaskTargetMapper;

    @Autowired
    protected UserInfoRemote userInfoRemote;

    @Autowired
    protected ProcessRemote processRemote;

    @Autowired
    protected RequestTypeRemote requestTypeRemote;

    @Autowired
    protected RequestRemote requestRemote;

    @Autowired
    protected RequestFlowRemote requestFlowRemote;


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean saveWipTask(WipTaskDTO wipTaskDTO) {

        WipTask wipTask = new WipTask();
        BeanUtil.copyProperties(wipTaskDTO, wipTask);
        wipTask.setCreatedTime(new Timestamp(DateUtil.current()));
        this.save(wipTask);

        wipTaskDTO.getPositionIds().forEach(
                id -> {
                    WipTaskTarget wipTaskTarget = new WipTaskTarget();
                    wipTaskTarget.setTaskId(wipTask.getId());
                    wipTaskTarget.setTargetId(id);
                    wipTaskTarget.setCreatedUser(AuthUtils.getCurrentUser());
                    wipTaskTarget.setCreatedTime(Timestamp.from(Instant.now()));
                    wipTaskTargetMapper.insert(wipTaskTarget);
                }
        );

        return true;

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean updateWipTask(WipTaskDTO wipTaskDTO) {

        WipTask wipTask = this.getById(wipTaskDTO.getId());
        if (ObjectUtil.isNull(wipTask)) {
            log.error("updateWipTask() The WipTask does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        BeanUtil.copyProperties(wipTaskDTO, wipTask);
        wipTask.setUpdatedUser(wipTaskDTO.getUpdatedUser());
        wipTask.setUpdatedTime(new Timestamp(DateUtil.current()));

        LambdaQueryWrapper<WipTaskTarget> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WipTaskTarget::getTaskId, wipTask.getId());
        wipTaskTargetMapper.delete(queryWrapper);

        wipTaskDTO.getPositionIds().forEach(
                id -> {
                    WipTaskTarget wipTaskTarget = new WipTaskTarget();
                    wipTaskTarget.setTaskId(wipTask.getId());
                    wipTaskTarget.setTargetId(id);
                    wipTaskTarget.setCreatedUser(AuthUtils.getCurrentUser());
                    wipTaskTarget.setCreatedTime(Timestamp.from(Instant.now()));
                    wipTaskTargetMapper.insert(wipTaskTarget);
                }
        );


        return this.updateById(wipTask);
    }

    @Override
    public Boolean saveOrUpdateBatch(List<WipTask> wipTaskList) {

        wipTaskList.forEach(wipTask -> {
            WipTask wipTaskParam = new WipTask();
            wipTaskParam.setId(wipTask.getId());
            if (ObjectUtil.isNotNull(wipTask.getId())) {
                wipTask.setId(wipTask.getId());
                wipTask.setUpdatedTime(new Timestamp(DateUtil.current()));
                LambdaUpdateWrapper<WipTask> lambdaUpdate = Wrappers.lambdaUpdate();
                lambdaUpdate.eq(WipTask::getId, wipTask.getId());
                update(wipTask, lambdaUpdate);
            } else {
                wipTask.setCreatedTime(new Timestamp(DateUtil.current()));
                save(wipTask);
            }
        });
        return true;
    }

    @Override
    public Boolean saveOrUpdateBatchByDTOList(List<WipTaskDTO> wipTaskDTOList) {

        List<WipTask> wipTaskList = BeanUtils.copyProperties(wipTaskDTOList, WipTask.class);
        return saveOrUpdateBatch(wipTaskList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteWipTaskLogical(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        WipTask wipTask = this.getById(id);

        if (ObjectUtil.isNull(wipTask)) {
            log.error("deleteWipTask() The WipTask does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        Assert.isFalse(new Integer(1).equals(wipTask.getTaskStatus()),
                "当前任务状态不能删除");

        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteWipTaskByIds(String ids) {
        Assert.notNull(ids, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
        List<String> idList = Arrays.asList(ids.split(","));
        if (CollectionUtil.isEmpty(idList)) {
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        idList.forEach(id -> {
            WipTask wipTask = this.getById(id);
            if (ObjectUtil.isNull(wipTask)) {
                log.error("deleteWipTask() The WipTask does not exist or has been deleted");
                throw new XdcWebException(ResponseEnum.ERROR);
            }
        });

        return this.removeByIds(idList);
    }

    private List<WipTask> queryWipTaskList(WipTaskFilterDTO wipTaskFilterDTO) {
        WipTaskQuery wipTaskQuery = BeanUtil.copyProperties(wipTaskFilterDTO, WipTaskQuery.class);

        return wipTaskMapper.queryWipTask(wipTaskQuery);
    }

    @Override
    public List<WipTaskVO> queryWipTaskVOList(WipTaskFilterDTO wipTaskFilterDTO) {
        return this.objectConversion(queryWipTaskList(wipTaskFilterDTO));
    }

    @Override
    public PageVO<WipTaskVO> queryWipTask(WipTaskFilterDTO wipTaskFilterDTO) {
        PageVO<WipTaskVO> pageVO = new PageVO<>();

        if (wipTaskFilterDTO.getCurrentPage() > NumberConstant.ZERO) {
            PageableUtils.basicPage(wipTaskFilterDTO.getCurrentPage(), wipTaskFilterDTO.getPageSize(),
                    wipTaskFilterDTO.getOrderType(), wipTaskFilterDTO.getOrderField());
        }

        WipTaskQuery wipTaskQuery = BeanUtil.copyProperties(wipTaskFilterDTO, WipTaskQuery.class);

//        if(Validator.equal(wipTaskFilterDTO.getTaskStatus(),NumberConstant.ZERO)){
        if (wipTaskFilterDTO.getRequestId() == null) {
            Assert.notNull(wipTaskFilterDTO.getCreatedUser(), ResponseEnum.WIP_TASK_CREATEDUSER_CANNOT_BE_NULL.getMessage());
            if (Validator.equal(wipTaskFilterDTO.getCreatedUser(), AuthConstant.ADMINISTRATOR)) {
                wipTaskQuery.setCreatedUser(null);
            }
        }

//        }

        List<WipTask> wipTaskList = wipTaskMapper.queryWipTask(wipTaskQuery);

        PageInfo<WipTask> pageInfo = new PageInfo<>(wipTaskList);

        List<WipTaskVO> records = this.objectConversion(wipTaskList);

        Set<Long> taskIdSet = records.stream().map(WipTaskVO::getId).collect(Collectors.toSet());
        if (ObjectUtil.isNotEmpty(taskIdSet)) {

            LambdaQueryWrapper<WipTaskTarget> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(WipTaskTarget::getTaskId, taskIdSet);
            Map<Long, List<WipTaskTarget>> targetMap = wipTaskTargetMapper.selectList(queryWrapper).stream()
                    .collect(Collectors.groupingBy(WipTaskTarget::getTaskId)
                    );

            records.forEach(record -> {
                if (ObjectUtil.isNotNull(record.getRequestId())) {
                    RequestVO requestVO =ResponseUtils.getResponse(requestRemote.findRequestById(record.getRequestId()));
                    record.setRequestVO(requestVO);
                }
                record.setPositionIds(targetMap.get(record.getId())
                        .stream().map(WipTaskTarget::getTargetId).collect(Collectors.toList()));
            });
        }

        PropertyUtils.copyProperties(pageInfo, pageVO, records);

        return pageVO;
    }

    @Override
    public WipTaskVO queryWipTaskById(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        return this.objectConversion(this.getById(id));
    }

    @Override
    public List<WipTaskVO> queryWipTaskByRequestIds(WipTaskFilterDTO wipTaskFilterDTO) {

        WipTaskQuery wipTaskQuery = BeanUtil.copyProperties(wipTaskFilterDTO, WipTaskQuery.class);

        return this.objectConversion(wipTaskMapper.queryWipTask(wipTaskQuery));
    }

}
